from django.shortcuts import render, redirect
from django.http import HttpResponse, JsonResponse
# Create your views here.
#  login状态保持，  authenticate 是django认证提供的用户校验的方法，成功返回用户对象
from django.contrib.auth import login, authenticate, logout
from django.views import View
# 合并购物车
from carts.utils import get_carts
from users.models import User
from django_redis import get_redis_connection
# 导入settings
from django.conf import settings
import re
# 定义装饰器   在每一次需要进行验证用户是否登录的时候需要验证
from django.utils.decorators import method_decorator
# 装饰方法，用来判断用户是否登录的时候使用
from django.contrib.auth.decorators import login_required
# 导入json模块
import json
# 导入模块进行加密
from itsdangerous import TimedJSONWebSignatureSerializer as TJS
# 导入模块 发送邮件
from django.core.mail import send_mail
# 调用异步请求
from celery_tasks.send_email.tasks import send_emails

#  跳转到首页------------------------------------------------------------------------------------
# class IndexVier(View):
#     def get(self, request):
#         return render(request, 'index.html')


# 跳转到注册页面--------------------------------------------------------------------------------------------
class UserRegisterView(View):
    def get(self, request):
        return render(request, 'register.html')

    def post(self, request):
        # 1.接收参数
        username = request.POST.get('user_name')
        password = request.POST.get('pwd')
        password2 = request.POST.get('cpwd')
        mobile = request.POST.get('phone')
        sms_code = request.POST.get('msg_code')
        allow = request.POST.get('allow')
        # 2.校验参数
        # 验证表单数据是否存在
        if username is None or password is None or password2 is None or mobile is None or sms_code is None or allow is None:
            return render(request, 'register.html', {'error_allow': 'true'})
        # 验证用户名长度：
        if len(username) < 5 or len(username) > 20:
            return render(request, 'register.html', {'error_allow': '用户名输入不对'}, status=400)
        # 验证用户名是否存在
        try:
            user = User.objects.get(username=username)
        except:
            user = None
        if user:
            return render(request, 'register.html', {'error_allow': '用户名已存在'}, status=400)
        # 验证两次密码是否一致
        if password != password2:
            return render(request, 'register.html', {'error_allow': '两次密码输入不一致'}, status=400)
        # 验证手机号格式：
        if not re.match(r'1[3-9]\d{9}', mobile):
            return render(request, 'register.html', status=400)
        # 验证手机号长度
        if len(mobile) != 11:
            return render(request, 'register.html', {'errow_allow': '手机号长度不正确'}, status=400)
        # 验证短信验证码
        if len(sms_code) != 6:
            return render(request, 'register.html', {'errow_allow': "短信验证码不正确"}, status=400)
        # 取出redis中的保存的当前手机号所对应的验证码
        client = get_redis_connection('verify_code')
        real_sms_code = client.get('sms_code_%s' % mobile)
        if real_sms_code is None:
            return render(request, 'register.html', {'errow_allow': '验证码已失效'})
        if sms_code != real_sms_code.decode():
            return render(request, 'register.html', {'error_message': '短信验证码错误'})
        # 保存数据到数据库中
        # 必须用create_userj进行保存   加密

        user=User.objects.create_user(username=username, password=password, mobile=mobile)
        # 注册保存数据成功后，进行状态保持
        login(request, user)
        return redirect('/')


# 用户名登录接口定义--------------------------------------------------------------------------------------------

class UserLoginView(View):
    def get(self, request):
        # 渲染返回登录页面
        return render(request, 'login.html')

    def post(self, request):
        # 1.获取前端传递的表单数据
        data = request.POST
        username = data.get('username')
        password = data.get('pwd')
        remembered = data.get('remembered')
        next = request.GET.get('next')
        if next is None:
            next = '/'
        # authentichcate是Django认证系统提供的用户校验方法，成功返回用户对象，失败返回None
        # 自动对密码进行解密
        user = authenticate(request, username=username, password=password)
        if user is None:
            return render(request, 'login.html', {'loginerror': '用户名或者密码错误'})
        # 3. 状态保持
        login(request, user)
        # 判断用户是否记选择记住登录
        if remembered == 'on':
            request.session.set_expiry(60 * 60 * 24 * 7)
            response = redirect(next)
            # 返回给前端用户名，用于显示
            response.set_cookie('username', username, 60 * 60 * 24 * 7)
        else:
            request.session.set_expiry('60*60*2')
            response = redirect(next)
            # 返回给前端用户名，用于显示
            response.set_cookie('username', username, 60 * 60 * 2)
        response = get_carts(request, response, user)
        # 跳转到首页
        return response


#   退出登录-----------------------------------------------------------------------------------------------
class UserLogoutView(View):
    '''
        退出登录
    '''

    def get(self, request):
        # 使用Django认证系统的发法退出登录，删除session
        logout(request)
        # 获取login登录页面的cookie数据
        response = redirect('/login/')
        # 获取cookie数据的  username
        if request.COOKIES.get('username'):
            # 删除cookie中的username
            response.delete_cookie('username')
        return response


# 用户中心----------------------------------------------------------------------------------------------------------

@method_decorator(login_required, name='dispatch')
class UserInfoView(View):
    def get(self, request):
        return render(request, 'user_center_info.html')


#  邮件发送--------------------------------------------------------------------------------------------------------
@method_decorator(login_required, name='dispatch')
class UserEmailView(View):
    # 前端发送的是一个put请求  携带者json数据
    def put(self, request):
        # 1.获取json数据   邮箱
        data = request.body.decode()
        # 2. 将json数据转化为字典类型
        data_dict = json.loads(data)
        to_email = data_dict['email']
        # 3.验证邮箱的有效性  往用户输入的邮箱中发送数据
        # 1-标题 2-邮箱信息内容 3- 用户看到发送人信息  4- 收件人的邮箱 html_message 将标签当html使用
        # 状态保持  login（request，user）  user = User.objects.filter(username = usekrname ,password = password)
        user = request.user
        tjs = TJS(settings.SECRET_KEY,300)
        # 对json数据进行加密
        token = tjs.dumps({'username':user.username,'email':to_email}).decode()
        # 邮箱验证
        verify_url = settings.EMAIL_VERIFY_URL+'?token=%s'%token
        # subject = '美多商城邮箱验证'
        # # 发送邮箱的内容
        # html_message = '<p>尊敬的用户您好！</p>' \
        #                '<p>感谢您使用美多商城。</p>' \
        #                '<p>您的邮箱为：%s 。请点击此链接激活您的邮箱：</p>' \
        #                '<p><a href="%s">%s<a></p>' % (to_email, verify_url, verify_url)
        # # 发送邮件
        # #          邮件标题           发件人       收件人邮箱 （列表）           发送的内容
        # send_mail (subject,'',settings.EMAIL_FROM,['SXM_CPP@163.com'],html_message = html_message)
        # 调用异步
    #     to_email  收件人邮箱地址     verify_url   邮箱验证地址    settings.EMAIL_FROM  发件人地址
        send_emails.delay(to_email,verify_url,settings.EMAIL_FROM)

        # 4.更新邮箱
        if not user.is_authenticated:
            return JsonResponse({'code':4104})
        # 将数据库中的email 的内容替换成  to_email
        user.email = to_email
        # save方法必须执行
        user.save()
        return JsonResponse({'code':0})

# ----------------------------------------------邮箱验证------------------------------------------------------------
# 邮箱进行验证后进行跳转
@method_decorator(login_required,name = 'dispatch')
class UserEmailVerifyView(View):
    def get(self,request):
        '''
            验证跳转到美多的邮箱认证链接
        :param request:
        :return:
        '''
        # 1.获取路径中加密后的token数据    token = tjs.dumps({'username'=user.username,'email'=user.to_emaile}).decode()
        # 提取的是 用户名 和 邮箱地址
        token = request.GET.get('token')
        if token is None:
            return HttpResponse('缺少token值',status=400)
        # 对token数据进行解密
        tjs = TJS(settings.SECRET_KEY,300)
        try:
            data = tjs.loads(token)
        except:
            return HttpResponse('无效的token值',status=400)
        # 3.提取token中的账户名 和 密码
        username= data.get('username') # 提取账户名
        email = data.get('email') # 提取邮箱

        # 判断提取的用户名和邮箱是否有一个为空
        if username is None or email is None:
            return HttpResponse('token值失效',status=400)
        # 4.验证username 和 email 的数据用户是否正确
        try:
            user = User.objects.get(username = username,email=email)
        except:
            return HttpResponse('数据错误',status=400)
        # 5.更新邮箱状态
        user.email_active = True
        user.save()
        # 6.返回结果
        return render(request,'user_center_info.html')
# ---------------------------修改密码-------------------------------------------------------------------------
@method_decorator(login_required,name = 'dispatch')
class ChangPWDView(View):
    def get(self,request):
        return render(request,'user_center_pass.html')
    def post(self,request):
        # 获取前段发送的from数据
        data = request.POST
        old_pwd = data.get('old_pwd')
        new_pwd = data.get('new_pwd')
        new_cpwd = data.get('new_pwd')
        # 校验密码
        user = request.user
        if not user.check_password(old_pwd):
            return render(request,'user_center_pass.html',{'errors_pwd':'密码错误'})
        if new_cpwd != new_pwd:
            return render(request,'user_center_pass.html',{'errors_pwd':'两次密码不一致'})
        # 更新密码
        user.set_password(new_pwd)
        user.save()
        return render(request,'user_center_pass.html',{'errors_pwd':'修改成功'})
























